package com.easylinkin.linkappapi.security.config;

import com.easylinkin.bases.redis.util.RedisUtil;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * <p>
 *     登录失败次数校验
 * </p>
 *
 * @author TongJie
 * @since 2021/2/6 11:33
 */
@Component
@Slf4j
public class LoginCountCheck {

    /**
     * 是否启用登录密码错误次数超限锁住用户机制
     */
    @Value("${linkapp.enableLoginCountCheck:false}")
    private Boolean enableLoginCountCheck;

    /**
     * 缓存中 登录次数前缀
     */
    private final static String LOGIN_COUNT = "loginCount_";
    /**
     * 规定时间内，最多允许的错误次数
     */
    private final static int MAX_ERROR_COUNT = 5;
    /**
     * -1标致 用户账号被锁
     */
    private final static Integer LOCKED_FLAG = -1;
    /**
     * 登录失败间隔 秒数
     */
    private final static Long LOGIN_FAILED_INTERVAL_SECONDS = 30 * 60L;
    /**
     * 用户锁定时间 秒数
     */
    private final static Long USER_LOCK_TIME_SECONDS = 30 * 60L;


    @Resource
    RedisUtil redisUtil;

    public boolean checkUserLocked(String username) {

        String loginCountUsername = LOGIN_COUNT + username;

//        -1 表示用户锁住了
        boolean locked = redisUtil.hasKey(loginCountUsername) && LOCKED_FLAG.equals(redisUtil.get(loginCountUsername));
        if (locked) {
            log.info("多次登录失败，用户被锁定");
        }
        return locked;
    }

    public void afterLoginHandler(boolean succcess, String username) {
//        根据配置是否禁用登录次数超限制锁用户的机制
        if (!enableLoginCountCheck) {
            return;
        }
        String loginCountUsername = LOGIN_COUNT + username;
        if (succcess) {
            if (redisUtil.hasKey(loginCountUsername) && !redisUtil.get(loginCountUsername).equals(LOCKED_FLAG)) {
                redisUtil.del(loginCountUsername);
                log.info("登录成功,删除缓存用户登录错误次数信息");
            }
            return;
        }
        if (!redisUtil.hasKey(loginCountUsername)) {
            // 设置 过期时间 xx秒
            redisUtil.set(loginCountUsername, 0, LOGIN_FAILED_INTERVAL_SECONDS);
        }
        if (redisUtil.get(loginCountUsername).equals(LOCKED_FLAG)) {
            log.info(loginCountUsername + "用户已被锁");
            return;
        }
//        错误次数增加1
        redisUtil.incr(loginCountUsername, 1);
        if (redisUtil.get(loginCountUsername).equals(MAX_ERROR_COUNT)) {
            // -1 表示用户锁住了 xx秒解锁
            redisUtil.set(loginCountUsername, LOCKED_FLAG, USER_LOCK_TIME_SECONDS);
        }
    }

}
